"""
使用 timeit 模块进行精确时间测试

运行测试:
python timeit_test.py
"""

import timeit
import statistics
from string_permutation import (
    permute_recursive,
    permute_iterative,
    permute_lexicographic,
    permute_heap,
    permute_generator
)


class TimeitBenchmark:
    """使用 timeit 进行精确的时间基准测试"""
    
    def __init__(self):
        self.algorithms = {
            "递归方法": permute_recursive,
            "迭代方法": permute_iterative,
            "字典序法": permute_lexicographic,
            "Heap算法": permute_heap,
        }
        
        # 生成器需要特殊处理
        self.generator_algorithms = {
            "生成器法": lambda s: list(permute_generator(s))
        }
    
    def format_time(self, seconds):
        """格式化时间显示"""
        if seconds >= 1:
            return f"{seconds:.6f} 秒"
        elif seconds >= 0.001:
            return f"{seconds * 1000:.3f} 毫秒"
        else:
            return f"{seconds * 1000000:.3f} 微秒"
    
    def benchmark_algorithm(self, func, test_string, number=100):
        """对单个算法进行基准测试"""
        # 使用 timeit.repeat 进行多次测试以获得更准确的结果
        times = timeit.repeat(
            lambda: func(test_string),
            number=number,
            repeat=5  # 重复5次测试
        )
        
        # 计算每次调用的平均时间
        times_per_call = [t / number for t in times]
        
        return {
            'min_time': min(times_per_call),
            'max_time': max(times_per_call),
            'mean_time': statistics.mean(times_per_call),
            'median_time': statistics.median(times_per_call),
            'stdev_time': statistics.stdev(times_per_call) if len(times_per_call) > 1 else 0,
            'all_times': times_per_call
        }
    
    def run_benchmark_suite(self, test_strings, iterations=100):
        """运行完整的基准测试套件"""
        print("⏱️  timeit 精确时间基准测试")
        print("=" * 80)
        print(f"测试配置: 每个算法运行 {iterations} 次，重复 5 轮测试")
        print("=" * 80)
        
        results = {}
        
        for test_string in test_strings:
            print(f"\n🔍 测试字符串: '{test_string}' (长度: {len(test_string)})")
            print("-" * 60)
            
            string_results = {}
            
            # 测试普通算法
            for algo_name, algo_func in self.algorithms.items():
                try:
                    print(f"测试 {algo_name}...", end=" ")
                    result = self.benchmark_algorithm(algo_func, test_string, iterations)
                    string_results[algo_name] = result
                    
                    print(f"✅ 平均: {self.format_time(result['mean_time'])}")
                    print(f"    最小: {self.format_time(result['min_time'])}")
                    print(f"    最大: {self.format_time(result['max_time'])}")
                    print(f"    中位: {self.format_time(result['median_time'])}")
                    print(f"    标差: {self.format_time(result['stdev_time'])}")
                    
                except Exception as e:
                    print(f"❌ 错误: {e}")
                    string_results[algo_name] = None
                
                print()
            
            # 测试生成器算法
            for algo_name, generator_func in self.generator_algorithms.items():
                try:
                    print(f"测试 {algo_name}...", end=" ")
                    result = self.benchmark_algorithm(generator_func, test_string, iterations)
                    string_results[algo_name] = result
                    
                    print(f"✅ 平均: {self.format_time(result['mean_time'])}")
                    print(f"    最小: {self.format_time(result['min_time'])}")
                    print(f"    最大: {self.format_time(result['max_time'])}")
                    print(f"    中位: {self.format_time(result['median_time'])}")
                    print(f"    标差: {self.format_time(result['stdev_time'])}")
                    
                except Exception as e:
                    print(f"❌ 错误: {e}")
                    string_results[algo_name] = None
                
                print()
            
            # 性能排名
            valid_results = {k: v for k, v in string_results.items() if v is not None}
            if valid_results:
                print("🏆 性能排名 (按平均时间):")
                sorted_algos = sorted(valid_results.items(), key=lambda x: x[1]['mean_time'])
                
                for i, (algo_name, result) in enumerate(sorted_algos, 1):
                    fastest_time = sorted_algos[0][1]['mean_time']
                    ratio = result['mean_time'] / fastest_time
                    print(f"  {i}. {algo_name}: {self.format_time(result['mean_time'])} ({ratio:.2f}x)")
            
            results[test_string] = string_results
            print("\n" + "=" * 60)
        
        return results
    
    def detailed_comparison(self, test_string="abcd"):
        """详细的算法比较"""
        print(f"\n📊 详细算法比较 - 测试字符串: '{test_string}'")
        print("=" * 80)
        
        # 进行更多次数的测试以获得更精确的结果
        results = {}
        
        all_algorithms = {**self.algorithms, **self.generator_algorithms}
        
        for algo_name, algo_func in all_algorithms.items():
            print(f"详细测试 {algo_name}...")
            
            # 不同次数的测试
            test_numbers = [10, 50, 100, 500]
            algo_results = {}
            
            for num in test_numbers:
                times = timeit.repeat(
                    lambda: algo_func(test_string),
                    number=num,
                    repeat=3
                )
                avg_time = min(times) / num  # 使用最佳时间
                algo_results[num] = avg_time
                print(f"  {num:3} 次: {self.format_time(avg_time)}")
            
            results[algo_name] = algo_results
            print()
        
        # 显示最终比较
        print("🎯 最终性能比较 (基于 100 次测试的最佳时间):")
        print("-" * 60)
        
        final_times = {name: data[100] for name, data in results.items()}
        sorted_final = sorted(final_times.items(), key=lambda x: x[1])
        
        fastest_time = sorted_final[0][1]
        
        for i, (algo_name, time_val) in enumerate(sorted_final, 1):
            ratio = time_val / fastest_time
            print(f"{i:2}. {algo_name:12}: {self.format_time(time_val):>12} ({ratio:5.2f}x)")
        
        return results


def run_timeit_tests():
    """运行 timeit 测试套件"""
    benchmark = TimeitBenchmark()
    
    # 基本测试套件
    test_strings = ["ab", "abc", "abcd", "abcde"]
    results = benchmark.run_benchmark_suite(test_strings, iterations=50)
    
    # 详细比较
    detailed_results = benchmark.detailed_comparison("abcd")
    
    print("\n" + "=" * 80)
    print("✨ timeit 基准测试完成!")
    print("=" * 80)
    print("\n📈 关键发现:")
    print("- timeit 提供了更精确的时间测量")
    print("- 多次重复测试减少了测量误差")
    print("- 统计分析提供了更可靠的性能数据")
    print("- 标准差显示了算法性能的稳定性")


if __name__ == "__main__":
    run_timeit_tests()
